package com.example.pufang.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.PageParamRequest;
import com.example.pufang.mapper.CollectMapper;
import com.example.pufang.mapper.HouseMapper;
import com.example.pufang.pojo.Collect;
import com.example.pufang.pojo.House;
import com.example.pufang.pojo.HouseViewLog;
import com.example.pufang.pojo.User;
import com.example.pufang.service.HouseService;
import com.example.pufang.service.HouseViewLogService;
import com.example.pufang.service.UserService;
import com.example.pufang.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class HouseServiceImpl extends ServiceImpl<HouseMapper, House> implements HouseService {

    @Autowired
    private HouseMapper houseMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private CollectMapper collectMapper;

    @Autowired
    private HouseViewLogService houseViewLogService;

    @Override
    public Boolean publish(House house) {

        house.setCreateTime(new Date());

        return this.save(house);
    }

    @Override
    public List<HouseListVo> getHouseList(PageParamRequest pageParamRequest, String searchText, String district,
                                          Integer room, Integer parlor, Integer lavatory, String order) {

        LambdaQueryWrapper<House> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(district), House::getDistrict, district)
                .eq(ObjectUtils.isNotNull(room), House::getRoom, room)
                .eq(ObjectUtils.isNotNull(parlor), House::getParlor, parlor)
                .eq(ObjectUtils.isNotNull(lavatory),House::getLavatory, lavatory)
                .eq(House::getIsDelete, false)
                .eq(House::getIsDisplay, true)
                .eq(House::getIsSold, false)
                .eq(House::getIsBan, false);

        if (StringUtils.isNotBlank(searchText)) {
            wrapper.and(w -> w.like(House::getTitle, searchText).or().like(House::getIntroduce, searchText));
        }
        if (StringUtils.isNotBlank(order)) {
            if (order.equals("时间升序")) {
                wrapper.orderByAsc(House::getUpdateTime);
            } else if (order.equals("时间降序")) {
                wrapper.orderByDesc(House::getUpdateTime);
            } else if (order.equals("价格升序")) {
                wrapper.orderByAsc(House::getPrice);
            } else if (order.equals("价格降序")) {
                wrapper.orderByDesc(House::getPrice);
            } else {
                // 默认按照发布时间降序排列
                wrapper.orderByDesc(House::getCreateTime);
            }
        } else {
            // 默认按照发布时间降序排列
            wrapper.orderByDesc(House::getCreateTime);
        }

        Page<House> housePage = new Page<>(pageParamRequest.getPage(), pageParamRequest.getLimit());
        IPage<House> houseIPage = houseMapper.selectPage(housePage , wrapper);
        List<HouseListVo> houseListVoList = new ArrayList<>();
        for (House house : houseIPage.getRecords()) {
            HouseListVo houseListVo = new HouseListVo();

            BeanUtils.copyProperties(house, houseListVo);
            houseListVoList.add(houseListVo);
        }
        return houseListVoList;
    }

    @Override
    public List<HouseListVo> getHouseCollectList(PageParamRequest pageParamRequest, Integer userId) {

        Integer start = (pageParamRequest.getPage()-1) * pageParamRequest.getLimit();
        Integer limit = pageParamRequest.getLimit();

        return houseMapper.selectCollectList(userId, start, limit);
    }

    @Override
    public List<HouseListVo> getHouseViewHistoryList(PageParamRequest pageParamRequest, Integer userId) {
        Integer start = (pageParamRequest.getPage()-1) * pageParamRequest.getLimit();
        Integer limit = pageParamRequest.getLimit();

        return houseMapper.selectViewHistoryList(userId, start, limit);
    }

    @Override
    public List<HouseListVo> getHouseListByUserId(PageParamRequest pageParamRequest, Integer id) {

        LambdaQueryWrapper<House> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(House::getIsDelete, false)
                .eq(House::getUserId, id);

        // 按照更新时间降序排列
        wrapper.orderByDesc(House::getUpdateTime);

        Page<House> housePage = new Page<>(pageParamRequest.getPage(), pageParamRequest.getLimit());
        IPage<House> houseIPage = houseMapper.selectPage(housePage , wrapper);
        List<HouseListVo> houseListVoList = new ArrayList<>();
        for (House house : houseIPage.getRecords()) {
            HouseListVo houseListVo = new HouseListVo();

            BeanUtils.copyProperties(house, houseListVo);
            houseListVoList.add(houseListVo);
        }
        return houseListVoList;
    }

    @Override
    public HouseFrontDetailVo getHouseDetail(String id, User user) {

        // 添加到浏览日志，不存在就添加，存在就更新
        HouseViewLog houseViewLog = new HouseViewLog();
        houseViewLog.setUserId(user.getId())
                .setHouseId(id)
                .setUpdateTime(new Date());
        LambdaQueryWrapper<HouseViewLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HouseViewLog::getUserId, user.getId())
                        .eq(HouseViewLog::getHouseId, id);
        houseViewLogService.saveOrUpdate(houseViewLog, wrapper);

        HouseFrontDetailVo detailVo = new HouseFrontDetailVo();

        House house = baseMapper.selectOne(new LambdaQueryWrapper<House>().eq(StringUtils.isNotBlank(id), House::getId, id));

        BeanUtils.copyProperties(house, detailVo);
        detailVo.setUsername(userService.getById(detailVo.getUserId()).getUsername());

        // 判断当前用户是否收藏此房源
        if (collectMapper.selectOne(new LambdaQueryWrapper<Collect>().eq(Collect::getHouseId, house.getId())
                .eq(Collect::getUserId, user.getId())) != null) {
            detailVo.setIsCollect(true);
        } else {
            detailVo.setIsCollect(false);
        }

        return detailVo;
    }

    @Override
    public PageListVo getListByPage(PageParamRequest pageParamRequest, String searchName, String searchRealName,
                                    String searchPhone) {

        PageListVo pageListVo = new PageListVo();

        int start = (pageParamRequest.getPage()-1)* pageParamRequest.getLimit();
        int limit = pageParamRequest.getLimit();

        List<HouseAdminListVo> logList = houseMapper.getListByPage(start, limit, searchName, searchRealName, searchPhone);

        // 获取总数
        Long total = houseMapper.count(searchName, searchRealName, searchPhone);

        // 获取总页数
        long l = total % pageParamRequest.getLimit();
        long totalPage = 0;
        if (l > 0) {
            totalPage = Math.floorDiv(total, pageParamRequest.getLimit()) + 1;
        } else {
            totalPage = Math.floorDiv(total, pageParamRequest.getLimit());
        }

        pageListVo.setPage((long) pageParamRequest.getPage())
                .setSize((long) pageParamRequest.getLimit())
                .setList(JSONObject.toJSONString(logList))
                .setTotal(total)
                .setTotalPage(totalPage);

        return pageListVo;
    }


    @Override
    public Boolean ban(House house) {
        House databaseHouse = baseMapper.selectById(house.getId());
        if (ObjectUtils.isNull(databaseHouse)) {
            return false;
        } else {
            databaseHouse.setIsBan(true);
        }
        return baseMapper.updateById(databaseHouse) > 0 ? true : false;
    }

    @Override
    public Boolean cancelBan(House house) {
        House databaseHouse = baseMapper.selectById(house.getId());
        if (ObjectUtils.isNull(databaseHouse)) {
            return false;
        } else {
            databaseHouse.setIsBan(false);
        }
        return this.updateById(databaseHouse);
    }
}
